package esmp.bootstrap.config;

import esmp.bootstrap.bean.LocalTaskExecutorImpl;
import esmp.bootstrap.bean.RedisEventSubscriber;
import esmp.bootstrap.bean.ServerEnvironment;
import esmp.jtt808.JTT808CmdExecutor;
import netty.session.SessionManager;
import netty.task.NettyDeferredTaskManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import redis.task.DeferredResultTaskManager;
import redis.task.LocalTaskExecutor;

/**
 * Created by dave on 18-7-20 下午10:05.
 * 基于Redis的Netty异常命令任务
 */
@Configuration
public class NettyTaskConfig {
    @Autowired ServerEnvironment environment;

    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 2);
        executor.setQueueCapacity(512);
        return executor;
    }

    @Bean
    public SessionManager sessionManager(StringRedisTemplate redisTemplate) {
        return new SessionManager(redisTemplate, environment.getServerId());
    }

    @Bean
    public NettyDeferredTaskManager nettyTaskManager(SessionManager sm, StringRedisTemplate template) {
        return new NettyDeferredTaskManager(sm, template);
    }

    @Bean
    public LocalTaskExecutor localTaskExecutor(NettyDeferredTaskManager nettyTaskManager) {
        return new LocalTaskExecutorImpl(nettyTaskManager);
    }

    @Bean
    public DeferredResultTaskManager deferredTaskManager(LocalTaskExecutor executor, StringRedisTemplate template) {
        return new DeferredResultTaskManager(template, executor, environment.getServerId());
    }

    @Bean
    public JTT808CmdExecutor cmdExecutor(SessionManager sm, DeferredResultTaskManager tm) {
        return new JTT808CmdExecutor(environment.getServerId(), sm, tm);
    }

    @Bean
    public RedisEventSubscriber subscriber(DeferredResultTaskManager taskManager) {
        return new RedisEventSubscriber(taskManager);
    }

    @Bean
    public RedisMessageListenerContainer listenerContainer(TaskExecutor executor, DeferredResultTaskManager taskManager,
                                                           RedisConnectionFactory connectionFactory, RedisEventSubscriber subscriber) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setTaskExecutor(executor);
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(subscriber, new ChannelTopic(taskManager.getTaskChannel()));
        container.addMessageListener(subscriber, new ChannelTopic(taskManager.getResultChannel()));
        return container;
    }

}
